package day30.homework;

import java.io.*;
import java.util.Properties;

/**
 * Properties配置文件操作演示类
 * 该类演示了如何使用Java Properties类来读取、修改和保存配置文件
 * Properties类是Hashtable的子类，专门用于处理属性文件（键值对形式）
 * 常用于存储应用程序的配置信息，如数据库连接参数、系统设置等
 */
public class hw3 {
    /**
     * 程序入口点方法
     * 执行完整的Properties文件操作流程：
     * 1. 读取配置文件内容
     * 2. 显示原始配置
     * 3. 修改配置项
     * 4. 保存修改后的配置到文件
     * 5. 处理可能发生的IO异常
     * @param args 命令行参数数组
     */
    public static void main(String[] args) {
        // 创建一个Properties对象，用于存储配置信息
        // Properties类继承自Hashtable，是专门用来处理属性文件的集合类
        // 它以键值对的形式存储数据，键和值都是String类型
        Properties prop = new Properties();
        
        // 设置配置文件的路径
        // 这里使用相对路径，指向当前项目目录下的day30/homework/db.properties文件
        // 相对路径是相对于项目根目录（即工作目录）而言的
        String filePath = "day30/homework/db.properties";
        
        // 使用try-catch语句块来处理可能发生的IO异常
        // 在文件操作中，FileNotFoundException和IOException是最常见的异常类型
        try {
            // 1. 读取配置文件
            // 在控制台输出提示信息，表明程序开始读取配置文件
            System.out.println("正在读取配置文件");
            
            // 创建文件输入流(FileInputStream)对象，用于从指定文件中读取字节数据
            // FileInputStream是InputStream的子类，专门用于从文件中读取数据
            // 构造函数参数是文件路径，如果文件不存在会抛出FileNotFoundException
            FileInputStream fis = new FileInputStream(filePath);
            
            // 使用Properties的load方法加载文件内容
            // load(InputStream inStream)方法从输入流中读取属性列表（键值对）
            // 文件内容应该是以键值对的形式存储，每行一个属性，格式为key=value
            // 也可以使用#或!作为注释符号
            prop.load(fis);
            
            // 显示原始配置内容
            // 在控制台输出提示信息，表明接下来显示的是修改前的配置内容
            System.out.println("原始配置内容：");
            // 使用list方法将Properties中的所有属性打印到指定的PrintStream中
            // 这里将所有属性打印到标准输出流System.out（即控制台）
            // list方法会以key=value的格式显示所有属性
            prop.list(System.out); // list方法可以将所有属性打印到控制台
            
            // 关闭文件输入流，释放系统资源
            // 关闭流是一个重要的编程习惯，可以避免资源泄露
            // 即使发生异常也应该关闭流，但在try-catch-finally结构中更安全
            fis.close();
            
            // 2. 修改配置内容
            // 在控制台输出提示信息，表明程序开始修改配置内容
            System.out.println("\n修改配置内容");
            
            // 使用setProperty方法修改属性值
            // setProperty(String key, String value)方法用于设置属性值
            // 如果指定的键已经存在，则更新其值；如果键不存在，则添加新的键值对
            // 这里修改了数据库连接相关的四个基本配置项
            prop.setProperty("driver", "com.mysql.Driver");      // 设置数据库驱动类名
            prop.setProperty("url", "localhost:3306");           // 设置数据库连接URL
            prop.setProperty("username", "root");                // 设置数据库用户名
            prop.setProperty("password", "123456");              // 设置数据库密码
            
            // 显示修改后的配置内容
            // 在控制台输出提示信息，表明接下来显示的是修改后的配置内容
            System.out.println("\n修改后的配置内容：");
            // 再次使用list方法显示修改后的所有属性
            prop.list(System.out);
            
            // 3. 将修改后的内容写回到文件中
            // 在控制台输出提示信息，表明程序开始保存修改后的配置
            System.out.println("\n正在保存修改后的配置");
            
            // 创建文件输出流(FileOutputStream)对象，用于向指定文件中写入字节数据
            // FileOutputStream是OutputStream的子类，专门用于向文件中写入数据
            // 如果文件不存在会自动创建，如果文件已存在则会覆盖原内容
            FileOutputStream fos = new FileOutputStream(filePath);
            
            // 使用Properties的store方法将内容保存到文件
            // store(OutputStream out, String comments)方法将属性列表写入输出流
            // 第一个参数是输出流，第二个参数是注释信息，会作为第一行写入文件（以#开头）
            // 注释通常用于说明文件的用途、修改时间等信息
            prop.store(fos, "Updated by hw3 program");
            
            // 关闭文件输出流，释放系统资源
            // 与输入流一样，输出流使用完毕后也需要关闭
            fos.close();
            
            // 提示用户操作成功完成
            // 在控制台输出成功信息，告知用户配置已成功写入文件
            System.out.println("\n配置已成功写入文件");
            
        } catch (IOException e) {
            // 捕获可能发生的IO异常，并打印错误信息
            // IOException是所有IO操作相关异常的父类，包括FileNotFoundException等
            System.out.println("操作配置文件时发生错误：");
            // 打印详细的异常堆栈信息，有助于调试和定位问题
            e.printStackTrace();
        }
        
        // 在控制台输出程序执行完毕的信息
        System.out.println("\n程序执行完毕");
    }
}